package com.gmail.hongyz.myfuse.dataengine;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.util.Assert;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.FrameworkServlet;
import org.springframework.web.util.WebUtils;

import net.sf.json.JSONObject;

import com.gmail.hongyz.myfuse.demo.action.DemoController;
import com.gmail.hongyz.myfuse.demo.action.DemoUserController;
import com.gmail.hongyz.myfuse.util.RequestUtils;

/**
 * Servlet implementation class for Servlet: DataEngineServlet
 *
 */
 public class DataEngineServlet extends FrameworkServlet {
   static final long serialVersionUID = 1L;
   
   private static final Log log = LogFactory.getLog(DataEngineServlet.class);
   
   private Map<String, String> actionMap = new HashMap<String, String>();
   
    /* (non-Java-doc)
	 * @see javax.servlet.http.HttpServlet#HttpServlet()
	 */
	public DataEngineServlet() {
		super();
	}
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		// TODO Auto-generated method stub
		super.init(config);
		actionMap.put("demo", "demoController");
		actionMap.put("demoUser", "demoUserController");
	}
	
	@Override
	protected void doService(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		// TODO Auto-generated method stub
		if (log.isDebugEnabled()) {
            log.debug("entering 'doPost' method...");
        }
		
		String action = request.getParameter("action");
		String methodName = request.getParameter("method");
		log.debug("action : " + action + ", method: " + methodName);
		JsonRequest jsonRequest = RequestUtils.convertToJsonRequest(request);
		log.debug("request json: " + jsonRequest);
		JsonResponseImpl jsonResponse = new JsonResponseImpl();
		String actionName = actionMap.get(action);
		Object bean = getWebApplicationContext().getBean(actionName);
		log.debug("registered action: " + bean);
		try {
			Method method = bean.getClass().getMethod(methodName, JsonRequest.class, JsonResponse.class);
			method.invoke(bean, jsonRequest, jsonResponse);
			
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
			jsonResponse.setFail("NoSuchMethod: " + e.getMessage());
		} catch (Exception e) {
			e.printStackTrace();
			jsonResponse.setFail("unkown error happened: " + e.getMessage());
		} finally {
			log.debug("response json: " + jsonResponse);
			response.getWriter().println(jsonResponse.toString());
			response.getWriter().flush();
			response.getWriter().close();
		}
	}
	
	protected WebApplicationContext initWebApplicationContext() throws BeansException {
		getServletContext().log(
				"Loading WebApplicationContext for Spring FrameworkServlet '" + getServletName() + "'");

		WebApplicationContext parent = getWebApplicationContext(getServletContext());
		WebApplicationContext wac = createWebApplicationContext(parent);
		if (logger.isInfoEnabled()) {
			logger.info("Using context class [" + wac.getClass().getName() + "] for servlet '" +
					getServletName() + "'");
		}

		if (isPublishContext()) {
			// Publish the context as a servlet context attribute.
			String attrName = getServletContextAttributeName();
			getServletContext().setAttribute(attrName, wac);
			if (logger.isDebugEnabled()) {
				logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
						"' as ServletContext attribute with name [" + attrName + "]");
			}
		}

		return wac;
	}
	
	private static WebApplicationContext getWebApplicationContext(ServletContext sc) {
		Assert.notNull(sc, "ServletContext must not be null");
		Object attr = sc.getAttribute(FrameworkServlet.SERVLET_CONTEXT_PREFIX + "action");
		if (attr == null) {
			return null;
		}
		if (attr instanceof RuntimeException) {
			throw (RuntimeException) attr;
		}
		if (attr instanceof Error) {
			throw (Error) attr;
		}
		if (!(attr instanceof WebApplicationContext)) {
			throw new IllegalStateException("Root context attribute is not of type WebApplicationContext: " + attr);
		}
		return (WebApplicationContext) attr;
	}
}